package org.example.designmode.completablefuture;

import org.example.utils.LogUtils;
import org.junit.Test;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;

public class CompletableFutureDemo {

    @Test
    public void runAsyncDemo() throws Exception{
        // 创建一个无输入值无返回值的任务
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            // 休眠1秒
            LogUtils.sleepSeconds(1000);
            LogUtils.info("run end...");
        });
        // 直接执行任务
        future.get(2, TimeUnit.SECONDS);
    }

    @Test
    public void supplyAsyncDemo() throws Exception {
        CompletableFuture<Long> future = CompletableFuture.supplyAsync(() -> {
           long start = System.currentTimeMillis();
            LogUtils.sleepSeconds(1000);
            long end = System.currentTimeMillis();
            return end - start;
        });

        System.out.println(future.get() + "毫秒");
    }

    @Test
    public void whenCompleteDemo() throws Exception {
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
           LogUtils.sleepSeconds(1000);
           LogUtils.info("抛出异常");
           throw new RuntimeException("触发异常");
        });

        future.whenComplete(new BiConsumer<Void, Throwable>() {
            @Override
            public void accept(Void unused, Throwable throwable) {
                LogUtils.info("执行完成");
            }
        });

        // 抛出异常时触发
        future.exceptionally(new Function<Throwable, Void>() {
            @Override
            public Void apply(Throwable throwable) {
                LogUtils.info(throwable.getMessage());
                return null;
            }
        });

        future.get();
    }

    @Test
    public void thenApplyDemo() throws Exception {
        CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
          long result = 10l + 10l;
          return result;
        }).thenApply(new Function<Long, Long>() {
            @Override
            public Long apply(Long aLong) {
                LogUtils.info("aLong = " + aLong);
                return aLong * aLong;
            }
            // 只输入不输出
        }).thenAccept(new Consumer<Long>() {
            @Override
            public void accept(Long aLong) {
                LogUtils.info("aLong = " + aLong);
            }
        }).thenRun(new Runnable() {
            @Override
            public void run() {
                LogUtils.info("计算完成");
            }
        });

        future.get();
    }
}
